#include "stdafx.h"

#include <memory>

#include "MainWndListMode.h"
#include "MainWndMemoMode.h"
#include "MemoFile.h"

std::auto_ptr<MemoFile> ListItem2Memo( const ListItem& item )
{
    return std::auto_ptr<MemoFile>( new MemoFile( item.FileName, item.unicode ) );
}

void MainWndListMode::Initialize()
{
    listView.Create(host.m_hWnd, host.rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_VSCROLL | 
        WS_CLIPCHILDREN | LVS_REPORT | LVS_SHOWSELALWAYS | 
        LVS_NOCOLUMNHEADER | LVS_OWNERDATA );

    listView.SetExtendedListViewStyle( LVS_EX_FULLROWSELECT );

    std::wstring workingDir = host.options->WorkingDir();
    listModel.LoadDir(workingDir);

    CRect rcClient;
    host.GetClientRect(&rcClient);

    listView.AddColumn( _T("item"), 0 );
    listView.SetColumnWidth(0, rcClient.Width() - 26);

    listView.SetModel(&listModel);

}

MainWndListMode::MainWndListMode( MainWnd& window ) 
    : host( window )
    , listView( host.listView )
    , listModel( host.listModel )
{
    controller = std::auto_ptr<ListModeController>( new ListModeController( this ) );

    if ( !listView.IsWindow() )
        Initialize();

    host.CreateSimpleCEMenuBar(IDR_MAINFRAME, SHCMBF_HMENU);

    host.m_hWndClient = listView.m_hWnd;

    if ( host.IsWindow() )
    {
        RecalcLayout();
        listView.ShowWindow( SW_SHOW );
    }
}

void MainWndListMode::RecalcLayout()
{
    if ( !listView.IsWindow() )
        return;

    CRect rect;
    host.GetClientRect(&rect);
    listView.SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
    listView.SetFocus();

    listView.UpdateItemWidth();

    int curSel = listView.GetNextItem(-1, LVNI_SELECTED);
    if (curSel != -1) listView.EnsureVisible(curSel, FALSE);
}

LRESULT MainWndListMode::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    RecalcLayout();
    return bHandled = FALSE;
}

LRESULT MainWndListMode::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
    MainWndMode* newMode = NULL;

    try
    {
        host.CurrentMode = NULL;
        listView.ShowWindow( SW_HIDE );

        newMode = new MainWndMemoMode( host, std::auto_ptr<MemoFile>( NULL ) );
        host.CurrentMode = newMode;

        delete this;
    }

    // hell ugly -> improve
    catch (...)
    {
        host.CurrentMode = this;
        host.m_hWndClient = listView.m_hWnd; 

        if ( newMode != NULL )
            delete newMode;
    }

/*
    std::wstring workingDir = options->WorkingDir();
    std::wstring fileName = GetNewFilename(workingDir);

    {
        EditDialog dlg(workingDir ^ fileName, options->NewInUnicode());
        dlg.DoModal();
    }

    model->LoadDir(workingDir);
    listView->UpdateModel();
//*/

    return 0;
}

LRESULT MainWndListMode::OnItemClick(int item, LPNMHDR lpNMHDR, BOOL bHandled)
{ 
    LPNMLISTVIEW nmLv = ( LPNMLISTVIEW )lpNMHDR;

    if (nmLv->iItem >= 0) {
        OpenItem(nmLv->iItem);
    }

    return bHandled = FALSE; 
}

void MainWndListMode::OpenItem(int i)
{
//    listView.SetRedraw(FALSE);

    {
        const ListItem *item = listModel.GetItem(i);

        // improve state switch immediately!
        MainWndMode* newMode = NULL;
        host.CurrentMode = NULL;
        listView.ShowWindow( SW_HIDE );

        newMode = new MainWndMemoMode( host, ListItem2Memo( *item ) );
        host.CurrentMode = newMode;

        delete this;
    }
/*

    // TODO: item position can be changed, remember
    listModel.UpdateItem(i);

    listView.SetRedraw();
    listView.Invalidate();
*/

}

LRESULT MainWndListMode::OnKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    /*
    if ( wParam == VK_RETURN ) {
    int curSel = listView->GetNextItem(-1, LVNI_SELECTED | LVNI_FOCUSED );
    if (curSel != -1) 
    OpenItem(curSel);
    }
    //*/

    CommandPtr command( controller->ProcessKey( wParam ) );
    if ( command.get() != NULL )
        host.executor->Do( *command );

    return bHandled = FALSE;
}

void MainWndListMode::OnLButtonDown( UINT, const CPoint& pt )
{
    CommandPtr command( controller->ProcessLButtonDown( pt ) );
    if ( command.get() != NULL )
        host.executor->Do( *command );
}

void MainWndListMode::OnLButtonUp( UINT, const CPoint& pt )
{
    CommandPtr command( controller->ProcessLButtonUp( pt ) );
    if ( command.get() != NULL )
        host.executor->Do( *command );
}

